package ar.com.solidussource.framework.backend.bo.crud;

import java.io.Serializable;
import java.util.List;

import ar.com.solidussource.framework.backend.bo.definition.BusinessObject;
import ar.com.solidussource.framework.backend.bo.exception.BusinessException;
import ar.com.solidussource.framework.backend.dao.filter.Filter;
import ar.com.solidussource.framework.backend.dao.filter.Page;
import ar.com.solidussource.framework.backend.dao.filter.Result;

/**
 * {@link BusinessObject} generico para operaciones CRUD con entidades de las
 * aplicaciones. <br>
 * La implementacion de este {@link BusinessObject} interactua con el
 * {@link GenericCRUDBO} para realizar operaciones crud y consultar paginadas y
 * filtradas en conjunto con el modelo de Filter y Page.
 */
public interface GenericCRUDBO<T> extends BusinessObject {
	/**
	 * Recupera todas las instancias persistentes de la clase del dao, no
	 * realiza paginacion. Para eso utilizar los metodos que permiten trabajar
	 * con {@link Filter} y {@link Page}
	 * 
	 * @return lista con todas las intancias persistentes de esa clase
	 * @throws PersistenceException
	 */
	public List<T> getAll() throws BusinessException;

	/**
	 * Recupera un objeto dado segun su id, en caso de que no exista retorna
	 * null
	 * 
	 * @param id
	 *            simple o compuesto del objeto que se quiere recuperar
	 * @return instancia recuperada o null si no se encuentra
	 * @throws BusinessException
	 */
	public T getById(Serializable id) throws BusinessException;

	/**
	 * Guarda un objeto o lo actualiza si es que ya esta guardado
	 * 
	 * @param instance
	 *            a guardar o actualizar
	 * @return la instancia guardada y actualizada. La retorna para obtener el
	 *         id en caso de que sea automatico
	 * @throws BusinessException
	 */
	public T saveOrUpdate(T instance) throws BusinessException;

	/**
	 * Guarda una nueva instancia persistente asumiendo que no existe en el
	 * repositorio
	 * 
	 * @param instance
	 *            nueva nunca guardada anteriormente
	 * @return la instancia guardada
	 * @throws BusinessException
	 */
	public T saveNew(T instance) throws BusinessException;

	/**
	 * Elimina un objeto persistente
	 * 
	 * @param instance
	 *            a eliminar
	 * @throws BusinessException
	 */
	public void delete(T instance) throws BusinessException;

	/**
	 * Retorna todos los objetos persistentes de la clase del dao que esten
	 * dentro de la pagina solicitada<br>
	 * Esta consulta no tiene filtro, para filtrar los resultados se debe
	 * utilizar el modelo de {@link Filter}<br>
	 * retorna un {@link Result} con la pagina retornada, la lista de objetos y
	 * la cantidad total de resultados
	 * 
	 * @param page
	 *            pagina que se esta buscando
	 * @return {@link Result} con los objetos de la pagina y cantidad total
	 * @throws BusinessException
	 */
	public Result<T> getAll(final Page page) throws BusinessException;

	/**
	 * Retorna todos los objetos persistentes de la clase utilizando el
	 * {@link Filter} para llenar el criteria de con los filtros y restritions
	 * de acuerdo a las neceidades de la aplicacion<br>
	 * cada aplicacion debera crear su implementacion de {@link Filter} para
	 * cada caso especifico<br>
	 * 
	 * @param filter
	 *            {@link Filter} custom de la aplicacion que llena el criteria.
	 *            En caso de que el filter sea nulo, funciona igual que el
	 *            metodo getAll(Page), simplemente lo ignora y no filtra por
	 *            nada
	 * @param page
	 *            {@link Page} con los datos de paginacion
	 * @return
	 * @throws BusinessException
	 */
	public Result<T> getAll(final Filter filter, final Page page) throws BusinessException;

	/**
	 * Retorna la cantidad de instancias persistidas que existen sobre la clase
	 * del dao que cumplan con los criterios del filtro seleccionado<br>
	 * En caso de que el filtro sea null se retorna la cantidad total de
	 * instnacias sin filtrar, el filtro se ignora
	 * 
	 * @param filter
	 *            para filtrar las clases, si es nulo se ignora y se cuentan
	 *            todas las instncias
	 * @return cantidad total de instancias
	 * @throws BusinessException
	 */
	public long count(final Filter filter) throws BusinessException;
}